Open In Colab

Ejercicio 4. Segmentación de Imágenes con U-Net¶

En este ejercicio trabajaremos con un ejemplo de Keras, donde se entrena un modelo para la segmentación de imágenes mediante un modelo de tipo U-Net. Un modelo de este tipo es básicamente un autoencoder, donde cada bloque de capas en el encoder está conectado mediante una conexión residual al bloque de capas simétrico en el decoder. Un ejemplo:

mask

Este tipo de modelos se emplean sobre todo en el tratamiento de imágenes médicas, pero el ejemplo que vamos a trabajar está diseñado para inferir la máscara de segmentación de imágenes de mascotas. El ejemplo en concreto es este.

1. Enunciado¶

Reproducir el ejemplo de Keras para la segmentación de imágenes con un modelo de tipo U-Net, y probar 2 variantes distintas de modelo, jugando con los filtros en cada bloque y con el número de bloques. Se hará una comparativa cualitativa, con 5 ejemplos distintos del dataset, y 5 imágenes de mascotas obtenidas de Internet (o propias).

2. Entrega¶

La entrega de este ejercicio se realiza a través de la tarea creada para tal efecto en Enseñanza Virtual. Tienes que entregar un notebook, y el HTML generado a partir de él, cuyas celdas estén ya evaluadas.

La estructura del notebook debe contener los siguientes apartados:

  1. Cabecera: nombre y apellidos.
  2. Preparación de los datos para ser usados en Keras.
  3. Modelos y configuraciones creados en Keras, razonando la modificación hecha al modelo original del ejemplo
  4. Entrenamiento y evaluación de cada modelo creado (un sub-apartado para cada uno).
  5. Evaluación de los modelos.
  6. Bibliografía utilizada (enlaces web, material de clase, libros, etc.).

2.1. Nota importante¶


HONESTIDAD ACADÉMICA Y COPIAS: un trabajo práctico es un examen, por lo que debe realizarse de manera individual. La discusión y el intercambio de información de carácter general con los compañeros se permite (e incluso se recomienda), pero NO AL NIVEL DE CÓDIGO. Igualmente el remitir código de terceros, OBTENIDO A TRAVÉS DE LA RED o cualquier otro medio, se considerará plagio.

Cualquier plagio o compartición de código que se detecte significará automáticamente la calificación de CERO EN LA ASIGNATURA para TODOS los alumnos involucrados. Por tanto a estos alumnos NO se les conservará, para futuras convocatorias, ninguna nota que hubiesen obtenido hasta el momento. SIN PERJUICIO DE OTRAS MEDIDAS DE CARÁCTER DISCIPLINARIO QUE SE PUDIERAN TOMAR.


3. Dataset¶

La celda para descargar el dataset en el ejemplo hace uso de curl, pero la descarga puede fallar (al menos en Google Colab). La descarga falla porque la descompresión con tar falla. En tal caso, recomiendo sustituir el comando curl -O por wget, para ambos ficheros del dataset.

In [ ]:
#Comentado para que no se pare aqui mi ejecución
In [1]:
#!curl -O https://thor.robots.ox.ac.uk/datasets/pets/images.tar.gz
#!curl -O https://thor.robots.ox.ac.uk/datasets/pets/annotations.tar.gz
In [2]:
#!tar -xf images.tar.gz
#!tar -xf annotations.tar.gz
In [ ]:
 

Alfonso Alarcón Tamayo¶

Preparación de los datos para ser usados en Keras.¶

Bueno en primer lugar tendremos que tener descargado el conjunto de imágenes y en mi caso localizarlo en la misma ubicación que este archivo, ya que estoy en jupyter en anaconda, el conjunto esta en las carpetas images y anotations respectivamente

In [3]:
import os

images_dir="images/"
trimaps_dir="annotations/trimaps/"

#tamaño de las imágenes
img_size= (160,160)

# representaciones (mascota,contorno y fondo)
num_classes=3

batch_size=64

# Ordenamos el conjunto de imagenes y los mapas para que esten en el mismo orden
def ordenar(directory, extension):
    file_paths = sorted([
        os.path.join(directory, fname)
        for fname in os.listdir(directory)
        if fname.endswith(extension) and not fname.startswith(".")
    ])
    print(f"Number of elements in {directory}: {len(file_paths)}")
    return file_paths


input_img_paths = ordenar(images_dir, ".jpg")
target_img_paths = ordenar(trimaps_dir, ".png")
Number of elements in images/: 7390
Number of elements in annotations/trimaps/: 7390

Vamos a ver un ejemplo para comprobar que se han guardado bien las imagenes y sus respectivas máscaras

In [4]:
from IPython.display import Image, display
from keras.utils import load_img
from PIL import ImageOps
import matplotlib.pyplot as plt

# Obtener las rutas de las imágenes
input_path = input_img_paths[76]
target_path = target_img_paths[76]

# Cargar las imágenes
input_img = load_img(input_path)
target_img = ImageOps.autocontrast(load_img(target_path))

# Creo dos subgráficos
fig, axes = plt.subplots(1, 2, figsize=(10, 5))

# Mostrar la imagen de entrada en el primer subgráfico
axes[0].imshow(input_img)
axes[0].set_title('Image')

# Mostrar la mascara en el segundo subgráfico
axes[1].imshow(target_img)
axes[1].set_title('Target')

#plt.tight_layout()
plt.show()

Ahora importamos el método del ejemplo de keras para generar el conjunto, aqui lo que esta haciendo es crear el dataset y con el load_img_maks: carga las imágenes, las decodifica, las redimensiona al tamaño de 160x160 que hemos especificado y las convierte, para el encoder tiene 3 canales ya que es a color y el decoder para la máscara 1 porque es en blanco y negro

In [5]:
import keras
import numpy as np
from tensorflow import data as tf_data
from tensorflow import image as tf_image
from tensorflow import io as tf_io


def get_dataset(
    batch_size,
    img_size,
    input_img_paths,
    target_img_paths,
    max_dataset_len=None,
):
    """Returns a TF Dataset."""

    def load_img_masks(input_img_path, target_img_path):
        input_img = tf_io.read_file(input_img_path)
        input_img = tf_io.decode_png(input_img, channels=3)
        input_img = tf_image.resize(input_img, img_size)
        input_img = tf_image.convert_image_dtype(input_img, "float32")

        target_img = tf_io.read_file(target_img_path)
        target_img = tf_io.decode_png(target_img, channels=1)
        target_img = tf_image.resize(target_img, img_size, method="nearest")
        target_img = tf_image.convert_image_dtype(target_img, "uint8")

        # como empieza en 1 restar uno para ir desde 0
        target_img -= 1
        return input_img, target_img

    # Reducir el tamaño
    if max_dataset_len:
        input_img_paths = input_img_paths[:max_dataset_len]
        target_img_paths = target_img_paths[:max_dataset_len]
    dataset = tf_data.Dataset.from_tensor_slices((input_img_paths, target_img_paths))
    dataset = dataset.map(load_img_masks, num_parallel_calls=tf_data.AUTOTUNE)
    return dataset.batch(batch_size)

Por último generamos de forma aleatoria y estratificada un conjunto de entrenamiento y validación, he dado un 80-20 aproximadamente.

In [6]:
import  random

aletoriedad = random.randint(1, 1000)
#Barajamos el conjunto
random.Random(aletoriedad).shuffle(input_img_paths)
random.Random(aletoriedad).shuffle(target_img_paths)

# vamos a darles un 20% a validación que es un total de unos 1500 elementos
train_images = input_img_paths[1500:]
train_target = target_img_paths[1500:]

val_images= input_img_paths[:1500]
val_target = target_img_paths[:1500]


train_dataset = get_dataset(batch_size,img_size,train_images,train_target,max_dataset_len=1000,)
valid_dataset = get_dataset(batch_size,img_size,val_images,val_target)

Modelos y configuraciones creados en Keras, razonando la modificación hecha al modelo original del ejemplo¶

Modelo 1
¶

En este primer modelo vamos a adaptar el método getmodel del ejemplo intentando adaptarlo mejor a nuestros datos , lo que he cambiado ha sido:

  • Nº filtros: He aumentado por una parte el número de filtros iniciales para que el modelo tenga una mayor capacidad para capturar características en la entrada.
  • Aumentando el número de filtros intento que el modelo aprenda características mas complejas y así pueda generalizar mejor ya que en el ejemplo tenía problemas para diferenciar en muchos casos a animales de elementos del entorno

  • Bloques: Como en el ejemplo, la pérdida del conjunto de validación era más alta que en el entrenamiento, eso significa que el modelo presenta algo de sobreajuste, he introducido un par de capas de dropout para reducir este problema

  • Learning rate: Haciendo pruebas con el lr encontré que en mi modelo con un learning rate algo mayor el rendimiento de este mejoró levemente.

In [18]:
from keras import layers


def get_model2(img_size, num_classes):
    inputs = keras.Input(shape=img_size + (3,))

    ### [First half of the network: downsampling inputs] ###

    # Entrada
    x = layers.Conv2D(64, 3, strides=2, padding="same")(inputs)
    x = layers.BatchNormalization()(x)
    x = layers.Activation("relu")(x)

    # residual
    previous_block_activation = x  

 
    for filters in [128,256,512]:
        x = layers.Activation("relu")(x)
        x = layers.SeparableConv2D(filters, 3, padding="same")(x)
        x = layers.BatchNormalization()(x)
        
        #Añadimos una capa aqui de dropdout para reducir el sobreajuste
        x = layers.Dropout(0.3)(x) 
        
        x = layers.Activation("relu")(x)
        x = layers.SeparableConv2D(filters, 3, padding="same")(x)
        x = layers.BatchNormalization()(x)

        x = layers.MaxPooling2D(3, strides=2, padding="same")(x)


        # residual
        residual = layers.Conv2D(filters, 1, strides=2, padding="same")(
            previous_block_activation
        )
        x = layers.add([x, residual])  # Add back residual
        previous_block_activation = x  # Set aside next residual



    for filters in [512,256,128, 64]:
        x = layers.Activation("relu")(x)
        x = layers.Conv2DTranspose(filters, 3, padding="same")(x)
        x = layers.BatchNormalization()(x)

        #Añadimos una capa en el decoder tb para intentar reducir el sobreajuste del modelo del ejemplo
        x = layers.Dropout(0.3)(x) 

        x = layers.Activation("relu")(x)
        x = layers.Conv2DTranspose(filters, 3, padding="same")(x)
        x = layers.BatchNormalization()(x)

        x = layers.UpSampling2D(2)(x)


        # Project residual
        residual = layers.UpSampling2D(2)(previous_block_activation)
        residual = layers.Conv2D(filters, 1, padding="same")(residual)
        x = layers.add([x, residual])  
        previous_block_activation = x  

    # clasificacion por pixel
    outputs = layers.Conv2D(num_classes, 3, activation="softmax", padding="same")(x)


    # Creamos el modelo
    model2 = keras.Model(inputs, outputs)
    return model2


# montamos y mostramos la estructura
model2 = get_model2(img_size, num_classes)
model2.summary()
Model: "model_2"
__________________________________________________________________________________________________
 Layer (type)                   Output Shape         Param #     Connected to                     
==================================================================================================
 input_3 (InputLayer)           [(None, 160, 160, 3  0           []                               
                                )]                                                                
                                                                                                  
 conv2d_18 (Conv2D)             (None, 80, 80, 64)   1792        ['input_3[0][0]']                
                                                                                                  
 batch_normalization_23 (BatchN  (None, 80, 80, 64)  256         ['conv2d_18[0][0]']              
 ormalization)                                                                                    
                                                                                                  
 activation_23 (Activation)     (None, 80, 80, 64)   0           ['batch_normalization_23[0][0]'] 
                                                                                                  
 activation_24 (Activation)     (None, 80, 80, 64)   0           ['activation_23[0][0]']          
                                                                                                  
 separable_conv2d_9 (SeparableC  (None, 80, 80, 128)  8896       ['activation_24[0][0]']          
 onv2D)                                                                                           
                                                                                                  
 batch_normalization_24 (BatchN  (None, 80, 80, 128)  512        ['separable_conv2d_9[0][0]']     
 ormalization)                                                                                    
                                                                                                  
 dropout_7 (Dropout)            (None, 80, 80, 128)  0           ['batch_normalization_24[0][0]'] 
                                                                                                  
 activation_25 (Activation)     (None, 80, 80, 128)  0           ['dropout_7[0][0]']              
                                                                                                  
 separable_conv2d_10 (Separable  (None, 80, 80, 128)  17664      ['activation_25[0][0]']          
 Conv2D)                                                                                          
                                                                                                  
 batch_normalization_25 (BatchN  (None, 80, 80, 128)  512        ['separable_conv2d_10[0][0]']    
 ormalization)                                                                                    
                                                                                                  
 max_pooling2d_6 (MaxPooling2D)  (None, 40, 40, 128)  0          ['batch_normalization_25[0][0]'] 
                                                                                                  
 conv2d_19 (Conv2D)             (None, 40, 40, 128)  8320        ['activation_23[0][0]']          
                                                                                                  
 add_14 (Add)                   (None, 40, 40, 128)  0           ['max_pooling2d_6[0][0]',        
                                                                  'conv2d_19[0][0]']              
                                                                                                  
 activation_26 (Activation)     (None, 40, 40, 128)  0           ['add_14[0][0]']                 
                                                                                                  
 separable_conv2d_11 (Separable  (None, 40, 40, 256)  34176      ['activation_26[0][0]']          
 Conv2D)                                                                                          
                                                                                                  
 batch_normalization_26 (BatchN  (None, 40, 40, 256)  1024       ['separable_conv2d_11[0][0]']    
 ormalization)                                                                                    
                                                                                                  
 dropout_8 (Dropout)            (None, 40, 40, 256)  0           ['batch_normalization_26[0][0]'] 
                                                                                                  
 activation_27 (Activation)     (None, 40, 40, 256)  0           ['dropout_8[0][0]']              
                                                                                                  
 separable_conv2d_12 (Separable  (None, 40, 40, 256)  68096      ['activation_27[0][0]']          
 Conv2D)                                                                                          
                                                                                                  
 batch_normalization_27 (BatchN  (None, 40, 40, 256)  1024       ['separable_conv2d_12[0][0]']    
 ormalization)                                                                                    
                                                                                                  
 max_pooling2d_7 (MaxPooling2D)  (None, 20, 20, 256)  0          ['batch_normalization_27[0][0]'] 
                                                                                                  
 conv2d_20 (Conv2D)             (None, 20, 20, 256)  33024       ['add_14[0][0]']                 
                                                                                                  
 add_15 (Add)                   (None, 20, 20, 256)  0           ['max_pooling2d_7[0][0]',        
                                                                  'conv2d_20[0][0]']              
                                                                                                  
 activation_28 (Activation)     (None, 20, 20, 256)  0           ['add_15[0][0]']                 
                                                                                                  
 separable_conv2d_13 (Separable  (None, 20, 20, 512)  133888     ['activation_28[0][0]']          
 Conv2D)                                                                                          
                                                                                                  
 batch_normalization_28 (BatchN  (None, 20, 20, 512)  2048       ['separable_conv2d_13[0][0]']    
 ormalization)                                                                                    
                                                                                                  
 dropout_9 (Dropout)            (None, 20, 20, 512)  0           ['batch_normalization_28[0][0]'] 
                                                                                                  
 activation_29 (Activation)     (None, 20, 20, 512)  0           ['dropout_9[0][0]']              
                                                                                                  
 separable_conv2d_14 (Separable  (None, 20, 20, 512)  267264     ['activation_29[0][0]']          
 Conv2D)                                                                                          
                                                                                                  
 batch_normalization_29 (BatchN  (None, 20, 20, 512)  2048       ['separable_conv2d_14[0][0]']    
 ormalization)                                                                                    
                                                                                                  
 max_pooling2d_8 (MaxPooling2D)  (None, 10, 10, 512)  0          ['batch_normalization_29[0][0]'] 
                                                                                                  
 conv2d_21 (Conv2D)             (None, 10, 10, 512)  131584      ['add_15[0][0]']                 
                                                                                                  
 add_16 (Add)                   (None, 10, 10, 512)  0           ['max_pooling2d_8[0][0]',        
                                                                  'conv2d_21[0][0]']              
                                                                                                  
 activation_30 (Activation)     (None, 10, 10, 512)  0           ['add_16[0][0]']                 
                                                                                                  
 conv2d_transpose_12 (Conv2DTra  (None, 10, 10, 512)  2359808    ['activation_30[0][0]']          
 nspose)                                                                                          
                                                                                                  
 batch_normalization_30 (BatchN  (None, 10, 10, 512)  2048       ['conv2d_transpose_12[0][0]']    
 ormalization)                                                                                    
                                                                                                  
 dropout_10 (Dropout)           (None, 10, 10, 512)  0           ['batch_normalization_30[0][0]'] 
                                                                                                  
 activation_31 (Activation)     (None, 10, 10, 512)  0           ['dropout_10[0][0]']             
                                                                                                  
 conv2d_transpose_13 (Conv2DTra  (None, 10, 10, 512)  2359808    ['activation_31[0][0]']          
 nspose)                                                                                          
                                                                                                  
 batch_normalization_31 (BatchN  (None, 10, 10, 512)  2048       ['conv2d_transpose_13[0][0]']    
 ormalization)                                                                                    
                                                                                                  
 up_sampling2d_17 (UpSampling2D  (None, 20, 20, 512)  0          ['add_16[0][0]']                 
 )                                                                                                
                                                                                                  
 up_sampling2d_16 (UpSampling2D  (None, 20, 20, 512)  0          ['batch_normalization_31[0][0]'] 
 )                                                                                                
                                                                                                  
 conv2d_22 (Conv2D)             (None, 20, 20, 512)  262656      ['up_sampling2d_17[0][0]']       
                                                                                                  
 add_17 (Add)                   (None, 20, 20, 512)  0           ['up_sampling2d_16[0][0]',       
                                                                  'conv2d_22[0][0]']              
                                                                                                  
 activation_32 (Activation)     (None, 20, 20, 512)  0           ['add_17[0][0]']                 
                                                                                                  
 conv2d_transpose_14 (Conv2DTra  (None, 20, 20, 256)  1179904    ['activation_32[0][0]']          
 nspose)                                                                                          
                                                                                                  
 batch_normalization_32 (BatchN  (None, 20, 20, 256)  1024       ['conv2d_transpose_14[0][0]']    
 ormalization)                                                                                    
                                                                                                  
 dropout_11 (Dropout)           (None, 20, 20, 256)  0           ['batch_normalization_32[0][0]'] 
                                                                                                  
 activation_33 (Activation)     (None, 20, 20, 256)  0           ['dropout_11[0][0]']             
                                                                                                  
 conv2d_transpose_15 (Conv2DTra  (None, 20, 20, 256)  590080     ['activation_33[0][0]']          
 nspose)                                                                                          
                                                                                                  
 batch_normalization_33 (BatchN  (None, 20, 20, 256)  1024       ['conv2d_transpose_15[0][0]']    
 ormalization)                                                                                    
                                                                                                  
 up_sampling2d_19 (UpSampling2D  (None, 40, 40, 512)  0          ['add_17[0][0]']                 
 )                                                                                                
                                                                                                  
 up_sampling2d_18 (UpSampling2D  (None, 40, 40, 256)  0          ['batch_normalization_33[0][0]'] 
 )                                                                                                
                                                                                                  
 conv2d_23 (Conv2D)             (None, 40, 40, 256)  131328      ['up_sampling2d_19[0][0]']       
                                                                                                  
 add_18 (Add)                   (None, 40, 40, 256)  0           ['up_sampling2d_18[0][0]',       
                                                                  'conv2d_23[0][0]']              
                                                                                                  
 activation_34 (Activation)     (None, 40, 40, 256)  0           ['add_18[0][0]']                 
                                                                                                  
 conv2d_transpose_16 (Conv2DTra  (None, 40, 40, 128)  295040     ['activation_34[0][0]']          
 nspose)                                                                                          
                                                                                                  
 batch_normalization_34 (BatchN  (None, 40, 40, 128)  512        ['conv2d_transpose_16[0][0]']    
 ormalization)                                                                                    
                                                                                                  
 dropout_12 (Dropout)           (None, 40, 40, 128)  0           ['batch_normalization_34[0][0]'] 
                                                                                                  
 activation_35 (Activation)     (None, 40, 40, 128)  0           ['dropout_12[0][0]']             
                                                                                                  
 conv2d_transpose_17 (Conv2DTra  (None, 40, 40, 128)  147584     ['activation_35[0][0]']          
 nspose)                                                                                          
                                                                                                  
 batch_normalization_35 (BatchN  (None, 40, 40, 128)  512        ['conv2d_transpose_17[0][0]']    
 ormalization)                                                                                    
                                                                                                  
 up_sampling2d_21 (UpSampling2D  (None, 80, 80, 256)  0          ['add_18[0][0]']                 
 )                                                                                                
                                                                                                  
 up_sampling2d_20 (UpSampling2D  (None, 80, 80, 128)  0          ['batch_normalization_35[0][0]'] 
 )                                                                                                
                                                                                                  
 conv2d_24 (Conv2D)             (None, 80, 80, 128)  32896       ['up_sampling2d_21[0][0]']       
                                                                                                  
 add_19 (Add)                   (None, 80, 80, 128)  0           ['up_sampling2d_20[0][0]',       
                                                                  'conv2d_24[0][0]']              
                                                                                                  
 activation_36 (Activation)     (None, 80, 80, 128)  0           ['add_19[0][0]']                 
                                                                                                  
 conv2d_transpose_18 (Conv2DTra  (None, 80, 80, 64)  73792       ['activation_36[0][0]']          
 nspose)                                                                                          
                                                                                                  
 batch_normalization_36 (BatchN  (None, 80, 80, 64)  256         ['conv2d_transpose_18[0][0]']    
 ormalization)                                                                                    
                                                                                                  
 dropout_13 (Dropout)           (None, 80, 80, 64)   0           ['batch_normalization_36[0][0]'] 
                                                                                                  
 activation_37 (Activation)     (None, 80, 80, 64)   0           ['dropout_13[0][0]']             
                                                                                                  
 conv2d_transpose_19 (Conv2DTra  (None, 80, 80, 64)  36928       ['activation_37[0][0]']          
 nspose)                                                                                          
                                                                                                  
 batch_normalization_37 (BatchN  (None, 80, 80, 64)  256         ['conv2d_transpose_19[0][0]']    
 ormalization)                                                                                    
                                                                                                  
 up_sampling2d_23 (UpSampling2D  (None, 160, 160, 12  0          ['add_19[0][0]']                 
 )                              8)                                                                
                                                                                                  
 up_sampling2d_22 (UpSampling2D  (None, 160, 160, 64  0          ['batch_normalization_37[0][0]'] 
 )                              )                                                                 
                                                                                                  
 conv2d_25 (Conv2D)             (None, 160, 160, 64  8256        ['up_sampling2d_23[0][0]']       
                                )                                                                 
                                                                                                  
 add_20 (Add)                   (None, 160, 160, 64  0           ['up_sampling2d_22[0][0]',       
                                )                                 'conv2d_25[0][0]']              
                                                                                                  
 conv2d_26 (Conv2D)             (None, 160, 160, 3)  1731        ['add_20[0][0]']                 
                                                                                                  
==================================================================================================
Total params: 8,199,619
Trainable params: 8,192,067
Non-trainable params: 7,552
__________________________________________________________________________________________________

Modelo 2
¶

En este segundo modelo lo que he intentado es reducir el modelo, ya que el anterior funciona bien pero es muy lento y tarda mucho (con tantos filtros y capas terminábamos con 8 millones de parametros), por lo que he intentado un modelo más simple(con menos características) con lo que tener un modelo simple pero más rápido que detecte a los animales aunque no los dibuje tan bien:

Probe en un principio a reducir aún más el número de capas y filtros, tambien cambié el MaxPooling por un AveragePooling y reducí el kernel de 3 a 2 esperando así simplificar el modelo, pero lo que me encontré fue que el modelo aunque fuese más rápido, tenía serias dificultades para detectar los bordes de los animales, se acercaba a la silueta del animal, pero marcaba mucho más imagen de lo que correspondedia, el modelo presentaba serios problemas para detectar características relevantes del animal para diferenciarlo del fondo, por eso al final opte por una versión del modelo 1 pero reduciendo la complejidad, así obtuve un paso intermedio entre el modelo desechado y el 1 donde se puede observar la silueta del animal, aunque no esté enteramente definida

  • Nº filtros: En este caso he reducido los filtros de las capa inicialiales e intermedias, así el modelo capturará menos características en la entrada y en los filtros siguientes

  • Bloques: He eliminado parte del bloque y además aunque había en un principio implementado en este caso tambien dropout para evitar el sobreajuste, pero con la reducción del modelo,al final el sobreajuste es mucho mas leve por lo que al final lo he eliminado, ya que empeoraba levemente el modelo.

Con estos cambios obtengo un modelo como ya he comentado más pequeño(pasando de 8 millones a 300.000 parámetros), pero más rápido, los resultados son menos definidos , ya que detecta más o menos los animales en la imágen, pero el contorno y el silueta no están totalmente definidos, un modelo así por ejemplo podría ser mejor para la detección simplemente.

In [19]:
from keras import layers


def get_model(img_size, num_classes):
    inputs = keras.Input(shape=img_size + (3,))

    ### [First half of the network: downsampling inputs] ###

    # Entry block
    x = layers.Conv2D(16, 3, strides=2, padding="same")(inputs)
    x = layers.BatchNormalization()(x)
    x = layers.Activation("relu")(x)

    previous_block_activation = x  # Set aside residual

    # Blocks 1, 2, 3 are identical apart from the feature depth.
    for filters in [32,64, 128]:
        x = layers.Activation("relu")(x)
        x = layers.SeparableConv2D(filters, 3, padding="same")(x)
        x = layers.BatchNormalization()(x)



        x = layers.MaxPooling2D(3, strides=2, padding="same")(x)

        # Project residual
        residual = layers.Conv2D(filters, 1, strides=2, padding="same")(
            previous_block_activation
        )
        x = layers.add([x, residual]) 
        previous_block_activation = x  

    ### [Second half of the network: upsampling inputs] ###

    for filters in [128, 64,32, 16]:
        x = layers.Activation("relu")(x)
        x = layers.Conv2DTranspose(filters, 3, padding="same")(x)
        x = layers.BatchNormalization()(x)


        x = layers.UpSampling2D(2)(x)

        #  residual
        residual = layers.UpSampling2D(2)(previous_block_activation)
        residual = layers.Conv2D(filters, 1, padding="same")(residual)
        x = layers.add([x, residual])  # Add back residual
        previous_block_activation = x  # Set aside next residual

    # clasificacion por pixel
    outputs = layers.Conv2D(num_classes, 3, activation="softmax", padding="same")(x)

    # creamos el modelo
    model = keras.Model(inputs, outputs)
    return model


# lo mostramos
model = get_model(img_size, num_classes)
model.summary()
Model: "model_3"
__________________________________________________________________________________________________
 Layer (type)                   Output Shape         Param #     Connected to                     
==================================================================================================
 input_4 (InputLayer)           [(None, 160, 160, 3  0           []                               
                                )]                                                                
                                                                                                  
 conv2d_27 (Conv2D)             (None, 80, 80, 16)   448         ['input_4[0][0]']                
                                                                                                  
 batch_normalization_38 (BatchN  (None, 80, 80, 16)  64          ['conv2d_27[0][0]']              
 ormalization)                                                                                    
                                                                                                  
 activation_38 (Activation)     (None, 80, 80, 16)   0           ['batch_normalization_38[0][0]'] 
                                                                                                  
 activation_39 (Activation)     (None, 80, 80, 16)   0           ['activation_38[0][0]']          
                                                                                                  
 separable_conv2d_15 (Separable  (None, 80, 80, 32)  688         ['activation_39[0][0]']          
 Conv2D)                                                                                          
                                                                                                  
 batch_normalization_39 (BatchN  (None, 80, 80, 32)  128         ['separable_conv2d_15[0][0]']    
 ormalization)                                                                                    
                                                                                                  
 max_pooling2d_9 (MaxPooling2D)  (None, 40, 40, 32)  0           ['batch_normalization_39[0][0]'] 
                                                                                                  
 conv2d_28 (Conv2D)             (None, 40, 40, 32)   544         ['activation_38[0][0]']          
                                                                                                  
 add_21 (Add)                   (None, 40, 40, 32)   0           ['max_pooling2d_9[0][0]',        
                                                                  'conv2d_28[0][0]']              
                                                                                                  
 activation_40 (Activation)     (None, 40, 40, 32)   0           ['add_21[0][0]']                 
                                                                                                  
 separable_conv2d_16 (Separable  (None, 40, 40, 64)  2400        ['activation_40[0][0]']          
 Conv2D)                                                                                          
                                                                                                  
 batch_normalization_40 (BatchN  (None, 40, 40, 64)  256         ['separable_conv2d_16[0][0]']    
 ormalization)                                                                                    
                                                                                                  
 max_pooling2d_10 (MaxPooling2D  (None, 20, 20, 64)  0           ['batch_normalization_40[0][0]'] 
 )                                                                                                
                                                                                                  
 conv2d_29 (Conv2D)             (None, 20, 20, 64)   2112        ['add_21[0][0]']                 
                                                                                                  
 add_22 (Add)                   (None, 20, 20, 64)   0           ['max_pooling2d_10[0][0]',       
                                                                  'conv2d_29[0][0]']              
                                                                                                  
 activation_41 (Activation)     (None, 20, 20, 64)   0           ['add_22[0][0]']                 
                                                                                                  
 separable_conv2d_17 (Separable  (None, 20, 20, 128)  8896       ['activation_41[0][0]']          
 Conv2D)                                                                                          
                                                                                                  
 batch_normalization_41 (BatchN  (None, 20, 20, 128)  512        ['separable_conv2d_17[0][0]']    
 ormalization)                                                                                    
                                                                                                  
 max_pooling2d_11 (MaxPooling2D  (None, 10, 10, 128)  0          ['batch_normalization_41[0][0]'] 
 )                                                                                                
                                                                                                  
 conv2d_30 (Conv2D)             (None, 10, 10, 128)  8320        ['add_22[0][0]']                 
                                                                                                  
 add_23 (Add)                   (None, 10, 10, 128)  0           ['max_pooling2d_11[0][0]',       
                                                                  'conv2d_30[0][0]']              
                                                                                                  
 activation_42 (Activation)     (None, 10, 10, 128)  0           ['add_23[0][0]']                 
                                                                                                  
 conv2d_transpose_20 (Conv2DTra  (None, 10, 10, 128)  147584     ['activation_42[0][0]']          
 nspose)                                                                                          
                                                                                                  
 batch_normalization_42 (BatchN  (None, 10, 10, 128)  512        ['conv2d_transpose_20[0][0]']    
 ormalization)                                                                                    
                                                                                                  
 up_sampling2d_25 (UpSampling2D  (None, 20, 20, 128)  0          ['add_23[0][0]']                 
 )                                                                                                
                                                                                                  
 up_sampling2d_24 (UpSampling2D  (None, 20, 20, 128)  0          ['batch_normalization_42[0][0]'] 
 )                                                                                                
                                                                                                  
 conv2d_31 (Conv2D)             (None, 20, 20, 128)  16512       ['up_sampling2d_25[0][0]']       
                                                                                                  
 add_24 (Add)                   (None, 20, 20, 128)  0           ['up_sampling2d_24[0][0]',       
                                                                  'conv2d_31[0][0]']              
                                                                                                  
 activation_43 (Activation)     (None, 20, 20, 128)  0           ['add_24[0][0]']                 
                                                                                                  
 conv2d_transpose_21 (Conv2DTra  (None, 20, 20, 64)  73792       ['activation_43[0][0]']          
 nspose)                                                                                          
                                                                                                  
 batch_normalization_43 (BatchN  (None, 20, 20, 64)  256         ['conv2d_transpose_21[0][0]']    
 ormalization)                                                                                    
                                                                                                  
 up_sampling2d_27 (UpSampling2D  (None, 40, 40, 128)  0          ['add_24[0][0]']                 
 )                                                                                                
                                                                                                  
 up_sampling2d_26 (UpSampling2D  (None, 40, 40, 64)  0           ['batch_normalization_43[0][0]'] 
 )                                                                                                
                                                                                                  
 conv2d_32 (Conv2D)             (None, 40, 40, 64)   8256        ['up_sampling2d_27[0][0]']       
                                                                                                  
 add_25 (Add)                   (None, 40, 40, 64)   0           ['up_sampling2d_26[0][0]',       
                                                                  'conv2d_32[0][0]']              
                                                                                                  
 activation_44 (Activation)     (None, 40, 40, 64)   0           ['add_25[0][0]']                 
                                                                                                  
 conv2d_transpose_22 (Conv2DTra  (None, 40, 40, 32)  18464       ['activation_44[0][0]']          
 nspose)                                                                                          
                                                                                                  
 batch_normalization_44 (BatchN  (None, 40, 40, 32)  128         ['conv2d_transpose_22[0][0]']    
 ormalization)                                                                                    
                                                                                                  
 up_sampling2d_29 (UpSampling2D  (None, 80, 80, 64)  0           ['add_25[0][0]']                 
 )                                                                                                
                                                                                                  
 up_sampling2d_28 (UpSampling2D  (None, 80, 80, 32)  0           ['batch_normalization_44[0][0]'] 
 )                                                                                                
                                                                                                  
 conv2d_33 (Conv2D)             (None, 80, 80, 32)   2080        ['up_sampling2d_29[0][0]']       
                                                                                                  
 add_26 (Add)                   (None, 80, 80, 32)   0           ['up_sampling2d_28[0][0]',       
                                                                  'conv2d_33[0][0]']              
                                                                                                  
 activation_45 (Activation)     (None, 80, 80, 32)   0           ['add_26[0][0]']                 
                                                                                                  
 conv2d_transpose_23 (Conv2DTra  (None, 80, 80, 16)  4624        ['activation_45[0][0]']          
 nspose)                                                                                          
                                                                                                  
 batch_normalization_45 (BatchN  (None, 80, 80, 16)  64          ['conv2d_transpose_23[0][0]']    
 ormalization)                                                                                    
                                                                                                  
 up_sampling2d_31 (UpSampling2D  (None, 160, 160, 32  0          ['add_26[0][0]']                 
 )                              )                                                                 
                                                                                                  
 up_sampling2d_30 (UpSampling2D  (None, 160, 160, 16  0          ['batch_normalization_45[0][0]'] 
 )                              )                                                                 
                                                                                                  
 conv2d_34 (Conv2D)             (None, 160, 160, 16  528         ['up_sampling2d_31[0][0]']       
                                )                                                                 
                                                                                                  
 add_27 (Add)                   (None, 160, 160, 16  0           ['up_sampling2d_30[0][0]',       
                                )                                 'conv2d_34[0][0]']              
                                                                                                  
 conv2d_35 (Conv2D)             (None, 160, 160, 3)  435         ['add_27[0][0]']                 
                                                                                                  
==================================================================================================
Total params: 297,603
Trainable params: 296,643
Non-trainable params: 960
__________________________________________________________________________________________________

Entrenamiento y evaluación de cada modelo creado (un sub-apartado para cada uno).¶

Modelo 1
¶

Este primer modelo llega a un resultado mejor , pero el tiempo de entrenamiento es mucho mayor, ya que el modelo es mucho más grande,podemos observar que aproximadamente alrededor de la época 30 el modelo se estanca un poco ya que la pérdida en validación desde este punto empieza a aumentar mientras que en el de entrenamiento prácticamente no mejora desde ese punto.

In [20]:
# He incrementado el lr consiguiendo así una mejora en el modelo
model2.compile(optimizer=keras.optimizers.Adam(0.001), loss="sparse_categorical_crossentropy")

callbacks = [
    keras.callbacks.ModelCheckpoint("oxford_segmentation.keras", save_best_only=True)
]

# vamos a usar el mismo nº de epochs y demás valores que el ejemplo para ver bien como varía los modelos y el rendimiento con
#mis cambios
epochs = 50
model2.fit(
    train_dataset,
    epochs=epochs,
    validation_data=valid_dataset,
    callbacks=callbacks,
    verbose=2,
)
Epoch 1/50
16/16 - 7s - loss: 5.3913 - val_loss: 371.7102 - 7s/epoch - 463ms/step
Epoch 2/50
16/16 - 5s - loss: 0.8953 - val_loss: 38.6621 - 5s/epoch - 339ms/step
Epoch 3/50
16/16 - 5s - loss: 0.7530 - val_loss: 3.5696 - 5s/epoch - 338ms/step
Epoch 4/50
16/16 - 6s - loss: 0.7096 - val_loss: 1.2586 - 6s/epoch - 350ms/step
Epoch 5/50
16/16 - 5s - loss: 0.6873 - val_loss: 1.2675 - 5s/epoch - 332ms/step
Epoch 6/50
16/16 - 5s - loss: 0.6693 - val_loss: 1.3208 - 5s/epoch - 335ms/step
Epoch 7/50
16/16 - 5s - loss: 0.6536 - val_loss: 1.3892 - 5s/epoch - 331ms/step
Epoch 8/50
16/16 - 5s - loss: 0.6364 - val_loss: 1.4652 - 5s/epoch - 340ms/step
Epoch 9/50
16/16 - 5s - loss: 0.6206 - val_loss: 1.5301 - 5s/epoch - 342ms/step
Epoch 10/50
16/16 - 5s - loss: 0.6050 - val_loss: 1.6333 - 5s/epoch - 343ms/step
Epoch 11/50
16/16 - 5s - loss: 0.5896 - val_loss: 1.6732 - 5s/epoch - 330ms/step
Epoch 12/50
16/16 - 5s - loss: 0.5763 - val_loss: 1.8008 - 5s/epoch - 327ms/step
Epoch 13/50
16/16 - 5s - loss: 0.5667 - val_loss: 1.7527 - 5s/epoch - 330ms/step
Epoch 14/50
16/16 - 5s - loss: 0.5543 - val_loss: 1.8574 - 5s/epoch - 328ms/step
Epoch 15/50
16/16 - 5s - loss: 0.5398 - val_loss: 2.0020 - 5s/epoch - 332ms/step
Epoch 16/50
16/16 - 5s - loss: 0.5198 - val_loss: 1.9613 - 5s/epoch - 332ms/step
Epoch 17/50
16/16 - 5s - loss: 0.5103 - val_loss: 2.1142 - 5s/epoch - 327ms/step
Epoch 18/50
16/16 - 5s - loss: 0.5016 - val_loss: 2.2252 - 5s/epoch - 326ms/step
Epoch 19/50
16/16 - 5s - loss: 0.4843 - val_loss: 2.3788 - 5s/epoch - 326ms/step
Epoch 20/50
16/16 - 5s - loss: 0.4662 - val_loss: 2.6194 - 5s/epoch - 327ms/step
Epoch 21/50
16/16 - 5s - loss: 0.4507 - val_loss: 2.5665 - 5s/epoch - 330ms/step
Epoch 22/50
16/16 - 5s - loss: 0.4402 - val_loss: 2.8032 - 5s/epoch - 326ms/step
Epoch 23/50
16/16 - 5s - loss: 0.4370 - val_loss: 2.9722 - 5s/epoch - 326ms/step
Epoch 24/50
16/16 - 5s - loss: 0.4191 - val_loss: 2.9280 - 5s/epoch - 326ms/step
Epoch 25/50
16/16 - 5s - loss: 0.4158 - val_loss: 3.1937 - 5s/epoch - 327ms/step
Epoch 26/50
16/16 - 5s - loss: 0.4129 - val_loss: 3.0817 - 5s/epoch - 326ms/step
Epoch 27/50
16/16 - 5s - loss: 0.4237 - val_loss: 2.7519 - 5s/epoch - 327ms/step
Epoch 28/50
16/16 - 5s - loss: 0.3928 - val_loss: 2.6778 - 5s/epoch - 327ms/step
Epoch 29/50
16/16 - 5s - loss: 0.3804 - val_loss: 2.1927 - 5s/epoch - 328ms/step
Epoch 30/50
16/16 - 5s - loss: 0.3697 - val_loss: 2.8078 - 5s/epoch - 333ms/step
Epoch 31/50
16/16 - 5s - loss: 0.3725 - val_loss: 3.1448 - 5s/epoch - 325ms/step
Epoch 32/50
16/16 - 5s - loss: 0.3700 - val_loss: 2.8378 - 5s/epoch - 332ms/step
Epoch 33/50
16/16 - 5s - loss: 0.3720 - val_loss: 2.3774 - 5s/epoch - 326ms/step
Epoch 34/50
16/16 - 5s - loss: 0.3624 - val_loss: 1.5224 - 5s/epoch - 326ms/step
Epoch 35/50
16/16 - 5s - loss: 0.3277 - val_loss: 1.2728 - 5s/epoch - 328ms/step
Epoch 36/50
16/16 - 5s - loss: 0.3140 - val_loss: 1.3731 - 5s/epoch - 325ms/step
Epoch 37/50
16/16 - 5s - loss: 0.2996 - val_loss: 1.2444 - 5s/epoch - 340ms/step
Epoch 38/50
16/16 - 6s - loss: 0.2922 - val_loss: 1.1563 - 6s/epoch - 348ms/step
Epoch 39/50
16/16 - 5s - loss: 0.2932 - val_loss: 1.3491 - 5s/epoch - 333ms/step
Epoch 40/50
16/16 - 6s - loss: 0.2961 - val_loss: 0.9672 - 6s/epoch - 350ms/step
Epoch 41/50
16/16 - 5s - loss: 0.2960 - val_loss: 1.1085 - 5s/epoch - 328ms/step
Epoch 42/50
16/16 - 5s - loss: 0.2855 - val_loss: 0.6999 - 5s/epoch - 341ms/step
Epoch 43/50
16/16 - 5s - loss: 0.2702 - val_loss: 0.6394 - 5s/epoch - 338ms/step
Epoch 44/50
16/16 - 5s - loss: 0.2647 - val_loss: 0.8920 - 5s/epoch - 330ms/step
Epoch 45/50
16/16 - 5s - loss: 0.2603 - val_loss: 0.7414 - 5s/epoch - 336ms/step
Epoch 46/50
16/16 - 5s - loss: 0.2611 - val_loss: 0.8108 - 5s/epoch - 338ms/step
Epoch 47/50
16/16 - 6s - loss: 0.2559 - val_loss: 0.6263 - 6s/epoch - 346ms/step
Epoch 48/50
16/16 - 5s - loss: 0.2441 - val_loss: 0.6887 - 5s/epoch - 340ms/step
Epoch 49/50
16/16 - 5s - loss: 0.2427 - val_loss: 0.8458 - 5s/epoch - 332ms/step
Epoch 50/50
16/16 - 5s - loss: 0.2434 - val_loss: 0.7350 - 5s/epoch - 331ms/step
Out[20]:
<keras.callbacks.History at 0x17ebd393d00>

Modelo 2
¶

Este segundo modelo es algo mas estable con respecto a los dos conjuntos ya que la perdida en ambos es muy parecida por lo que el sobrejuste es mínimo, aún sin dropout simplificando la entrada y el modelo tanto en filtros o bloques ha conseguido un valor de perdida parecido y pequeño para ambos.

In [21]:
model.compile(optimizer=keras.optimizers.Adam(1e-4), loss="sparse_categorical_crossentropy")

callbacks = [
    keras.callbacks.ModelCheckpoint("oxford_segmentation.keras", save_best_only=True)
]


epochs = 50
model.fit(
    train_dataset,
    epochs=epochs,
    validation_data=valid_dataset,
    callbacks=callbacks,
    verbose=2,
)
Epoch 1/50
16/16 - 2s - loss: 1.9886 - val_loss: 1.8274 - 2s/epoch - 149ms/step
Epoch 2/50
16/16 - 1s - loss: 1.3059 - val_loss: 1.4989 - 1s/epoch - 76ms/step
Epoch 3/50
16/16 - 1s - loss: 1.1048 - val_loss: 1.3380 - 1s/epoch - 74ms/step
Epoch 4/50
16/16 - 1s - loss: 1.0009 - val_loss: 1.2351 - 1s/epoch - 72ms/step
Epoch 5/50
16/16 - 1s - loss: 0.9372 - val_loss: 1.2413 - 1s/epoch - 67ms/step
Epoch 6/50
16/16 - 1s - loss: 0.8936 - val_loss: 1.2540 - 1s/epoch - 71ms/step
Epoch 7/50
16/16 - 1s - loss: 0.8598 - val_loss: 1.2596 - 1s/epoch - 73ms/step
Epoch 8/50
16/16 - 1s - loss: 0.8328 - val_loss: 1.2609 - 1s/epoch - 70ms/step
Epoch 9/50
16/16 - 1s - loss: 0.8109 - val_loss: 1.2593 - 1s/epoch - 70ms/step
Epoch 10/50
16/16 - 1s - loss: 0.7927 - val_loss: 1.2520 - 1s/epoch - 73ms/step
Epoch 11/50
16/16 - 1s - loss: 0.7772 - val_loss: 1.2384 - 1s/epoch - 69ms/step
Epoch 12/50
16/16 - 1s - loss: 0.7639 - val_loss: 1.2193 - 1s/epoch - 79ms/step
Epoch 13/50
16/16 - 1s - loss: 0.7521 - val_loss: 1.1946 - 1s/epoch - 76ms/step
Epoch 14/50
16/16 - 1s - loss: 0.7416 - val_loss: 1.1657 - 1s/epoch - 75ms/step
Epoch 15/50
16/16 - 1s - loss: 0.7322 - val_loss: 1.1334 - 1s/epoch - 75ms/step
Epoch 16/50
16/16 - 1s - loss: 0.7235 - val_loss: 1.0979 - 1s/epoch - 78ms/step
Epoch 17/50
16/16 - 1s - loss: 0.7156 - val_loss: 1.0606 - 1s/epoch - 79ms/step
Epoch 18/50
16/16 - 1s - loss: 0.7081 - val_loss: 1.0225 - 1s/epoch - 79ms/step
Epoch 19/50
16/16 - 1s - loss: 0.7012 - val_loss: 0.9846 - 1s/epoch - 76ms/step
Epoch 20/50
16/16 - 1s - loss: 0.6946 - val_loss: 0.9472 - 1s/epoch - 81ms/step
Epoch 21/50
16/16 - 1s - loss: 0.6885 - val_loss: 0.9113 - 1s/epoch - 73ms/step
Epoch 22/50
16/16 - 1s - loss: 0.6826 - val_loss: 0.8782 - 1s/epoch - 77ms/step
Epoch 23/50
16/16 - 1s - loss: 0.6770 - val_loss: 0.8473 - 1s/epoch - 77ms/step
Epoch 24/50
16/16 - 1s - loss: 0.6716 - val_loss: 0.8196 - 1s/epoch - 86ms/step
Epoch 25/50
16/16 - 1s - loss: 0.6665 - val_loss: 0.7954 - 1s/epoch - 83ms/step
Epoch 26/50
16/16 - 1s - loss: 0.6614 - val_loss: 0.7744 - 1s/epoch - 81ms/step
Epoch 27/50
16/16 - 1s - loss: 0.6566 - val_loss: 0.7562 - 1s/epoch - 78ms/step
Epoch 28/50
16/16 - 1s - loss: 0.6519 - val_loss: 0.7404 - 1s/epoch - 79ms/step
Epoch 29/50
16/16 - 1s - loss: 0.6473 - val_loss: 0.7267 - 1s/epoch - 76ms/step
Epoch 30/50
16/16 - 1s - loss: 0.6428 - val_loss: 0.7147 - 1s/epoch - 78ms/step
Epoch 31/50
16/16 - 1s - loss: 0.6384 - val_loss: 0.7048 - 1s/epoch - 77ms/step
Epoch 32/50
16/16 - 1s - loss: 0.6341 - val_loss: 0.6964 - 1s/epoch - 80ms/step
Epoch 33/50
16/16 - 1s - loss: 0.6299 - val_loss: 0.6896 - 1s/epoch - 75ms/step
Epoch 34/50
16/16 - 1s - loss: 0.6257 - val_loss: 0.6838 - 1s/epoch - 74ms/step
Epoch 35/50
16/16 - 1s - loss: 0.6217 - val_loss: 0.6789 - 1s/epoch - 78ms/step
Epoch 36/50
16/16 - 1s - loss: 0.6177 - val_loss: 0.6746 - 1s/epoch - 77ms/step
Epoch 37/50
16/16 - 1s - loss: 0.6138 - val_loss: 0.6709 - 1s/epoch - 76ms/step
Epoch 38/50
16/16 - 1s - loss: 0.6100 - val_loss: 0.6673 - 1s/epoch - 77ms/step
Epoch 39/50
16/16 - 1s - loss: 0.6062 - val_loss: 0.6641 - 1s/epoch - 75ms/step
Epoch 40/50
16/16 - 1s - loss: 0.6025 - val_loss: 0.6612 - 1s/epoch - 75ms/step
Epoch 41/50
16/16 - 1s - loss: 0.5989 - val_loss: 0.6584 - 1s/epoch - 78ms/step
Epoch 42/50
16/16 - 1s - loss: 0.5954 - val_loss: 0.6558 - 1s/epoch - 77ms/step
Epoch 43/50
16/16 - 1s - loss: 0.5919 - val_loss: 0.6533 - 1s/epoch - 75ms/step
Epoch 44/50
16/16 - 1s - loss: 0.5884 - val_loss: 0.6511 - 1s/epoch - 75ms/step
Epoch 45/50
16/16 - 1s - loss: 0.5850 - val_loss: 0.6489 - 1s/epoch - 77ms/step
Epoch 46/50
16/16 - 1s - loss: 0.5817 - val_loss: 0.6469 - 1s/epoch - 79ms/step
Epoch 47/50
16/16 - 1s - loss: 0.5783 - val_loss: 0.6450 - 1s/epoch - 75ms/step
Epoch 48/50
16/16 - 1s - loss: 0.5751 - val_loss: 0.6432 - 1s/epoch - 78ms/step
Epoch 49/50
16/16 - 1s - loss: 0.5719 - val_loss: 0.6412 - 1s/epoch - 75ms/step
Epoch 50/50
16/16 - 1s - loss: 0.5687 - val_loss: 0.6397 - 1s/epoch - 75ms/step
Out[21]:
<keras.callbacks.History at 0x17ee472c2b0>
In [ ]:
 

Evaluación de los modelos.¶

Para la evaluación de los modelos comprobaremos por una parte como dice el enunciado 5 ejemplos con elementos del conjunto y en una segunda vuelta con imágenes de intenet de perros para comprobar las predicciones sobre nuevas imágenes

Modelo 1
¶

En este primer modelo podemos ver que las predicciones son bastante, estables, el cotorno de los animales esta bien formado y distingue bien las partes de la imagen.

Con respecto a las imágenes nuevas las predicciones son menos acertadas,aunque detecta la silueta de los animales, dependiendo del fondo tiene dificultades para determinar las patas de los animales.

Imágenes del conjunto

In [35]:
import matplotlib.pyplot as plt
from keras.utils import load_img
from PIL import ImageOps


#Definimos un pequeño metodo para mostrar las imagenes y predicciones en una misma imagen
def display_images(images, titles):
    num_images = len(images)

    # Un subgrafico por imagen
    fig, axes = plt.subplots(1, num_images, figsize=(15, 5))

    # Iterar sobre las imágenes y títulos y mostrarlas en los subgráficos
    for i in range(num_images):
        axes[i].imshow(images[i])
        axes[i].set_title(titles[i])
    plt.show()


val_dataset = get_dataset(
    batch_size, img_size, val_images, val_target
)
val_preds = model2.predict(val_dataset)


# Índices de las 5 imaágenes a mostrar
selected_indices = [ 15 ,25, 30, 5, 100]

# Muestra ejemplos seleccionados
for i in selected_indices:
    # Imagen original
    input_img = load_img(val_images[i])

    #  Mostramos la mascara
    target_img = ImageOps.autocontrast(load_img(val_target[i]))

    # Finalmente la prediccion
    mask_img = np.argmax(val_preds[i], axis=-1)
    mask_img = np.expand_dims(mask_img, axis=-1)
    mask_img = ImageOps.autocontrast(keras.utils.array_to_img(mask_img))

    # Mostramos cada una de ellas
    display_images([input_img, target_img, mask_img], ["Original", "Target", "Predicction"])
24/24 [==============================] - 2s 85ms/step

Imágenes nuevas

In [39]:
from os import listdir
from os.path import isfile, join
import keras
import numpy as np
import tensorflow as tf
from tensorflow import data as tf_data
from tensorflow import image as tf_image
from tensorflow import io as tf_io


# cargamos el directorio con las imágenes de internet y las metemos en images
path = "perros/"

#Obtenemos el nombre d elos archivos para el for
image = [f for f in listdir(path) if isfile(join(path, f))]


# Esta parte es como el ejemplo de keras

# Itera sobre cada imagen y muestra la imagen y la predicción
for image_file in image:
    # Construye la ruta completa de la imagen
    image_path = join(path, image_file)

    # Cargamos y procesamos la imagen como en el conjunto del ejemplo
    internet_img = tf_io.read_file(image_path)
    #decodificamos y especificamos 3 canales 
    internet_img = tf_io.decode_png(internet_img, channels=3)
    # ajustamos el tamaño a la entrada
    internet_img = tf_image.resize(internet_img, (160, 160))  
    internet_img = tf_image.convert_image_dtype(internet_img, "float32")
    internet_img_array = tf.expand_dims(internet_img, axis=0)

    # calculamos la predicción 
    prediction = model2.predict(internet_img_array)

    # transformamos la máscara a imagen para ver el resultaod d ela predicción
    prediction = np.argmax(prediction[0], axis=-1)
    prediction = np.expand_dims(prediction, axis=-1)
    prediction = ImageOps.autocontrast(tf.keras.utils.array_to_img(prediction))

    # Mostramos imagen y predicción por cada imagen
    display(Image(filename=image_path, width=160, height=160))  # Ajusta el tamaño a 160x160
    display(prediction)
1/1 [==============================] - 0s 18ms/step
1/1 [==============================] - 0s 23ms/step
1/1 [==============================] - 0s 19ms/step
1/1 [==============================] - 0s 23ms/step
1/1 [==============================] - 0s 18ms/step
1/1 [==============================] - 0s 20ms/step

Modelo 2
¶

Este segundo ejemplo tenemos un resultado algo peor que el anterior a costa de tener un modelo más rápido y sencillo, detecta mas o menos las siluetas pero tiene problemas para identificar algunas partes de los animales con respecto al fondo

En las imágenes de internet el resultado es más irregular, detecta en la imagen las zonas donde se situa el animal , pero presenta problemas para representar a este y su contorno

Imágenes del conjunto

In [37]:
import matplotlib.pyplot as plt
from keras.utils import load_img
from PIL import ImageOps

#Definimos un pequeño metodo para mostrar las imagenes y predicciones en una misma imagen

val_preds = model.predict(val_dataset)

# Índices de las 5 imaágenes a mostrar
selected_indices = [ 15 ,25, 30, 5, 100]

# Muestra ejemplos seleccionados
for i in selected_indices:
    # Imagen original
    input_img = load_img(val_images[i])

    #  Mostramos la mascara
    target_img = ImageOps.autocontrast(load_img(val_target[i]))

    # Finalmente la prediccion
    mask_img = np.argmax(val_preds[i], axis=-1)   
    mask_img = np.expand_dims(mask_img, axis=-1) 
    mask_img = ImageOps.autocontrast(keras.utils.array_to_img(mask_img))

    # Mostramos cada una de ellas
    display_images([input_img, target_img, mask_img], ["Original", "Target", "Predicction"])
    
24/24 [==============================] - 1s 25ms/step

Imágenes nuevas

In [40]:
# Itera sobre cada imagen y muestra la imagen y la predicción
for image_file in image:
    # ruta completa de la imagen
    image_path = join(path, image_file)

    # Cargamos y procesamos la imagen como en el conjunto del ejemplo
    internet_img = tf_io.read_file(image_path)
    #decodificamos y especificamos 3 canales 
    internet_img = tf_io.decode_png(internet_img, channels=3)
    # ajustamos el tamaño a la entrada
    internet_img = tf_image.resize(internet_img, (160, 160))  
    internet_img = tf_image.convert_image_dtype(internet_img, "float32")
    internet_img_array = tf.expand_dims(internet_img, axis=0)

    # calculamos la predicción con el modelo
    prediction = model.predict(internet_img_array)

    # transformamos la máscara a imagen para ver el resultaod d ela predicción
    prediction = np.argmax(prediction[0], axis=-1)
    prediction = np.expand_dims(prediction, axis=-1)
    prediction = ImageOps.autocontrast(tf.keras.utils.array_to_img(prediction))

    # Mostramos imagen y predicción por cada imagen
    display(Image(filename=image_path, width=160, height=160))  # Ajusta el tamaño a 160x160
    display(prediction)
1/1 [==============================] - 0s 13ms/step
1/1 [==============================] - 0s 14ms/step
1/1 [==============================] - 0s 13ms/step
1/1 [==============================] - 0s 18ms/step
1/1 [==============================] - 0s 19ms/step
1/1 [==============================] - 0s 14ms/step

Bibliografía utilizada (enlaces web, material de clase, libros, etc.).¶

https://keras.io/examples/vision/oxford_pets_image_segmentation/

Diapositivas y videos de clase

https://colab.research.google.com/github/miguelamda/DL/blob/master/7.%20Modelos%20Generativos/Practica7.5.%20Introducci%C3%B3n%20a%20VAEs.ipynb

https://pyimagesearch.com/2022/02/21/u-net-image-segmentation-in-keras/

https://youtu.be/3v7sYqigeSc?si=Gx3m3ph7xAY3j0Ul

In [ ]:
 
In [ ]: